#!/usr/bin/env python
# coding=utf-8
# @FileName :client.py
# @Time     :2022/2/9 19:12
# @Author   :ZXC
# @Desc     :
from typing import Any

from loguru import logger
from requests import Session

from tools.common import allure_title, allure_step_no, allure_step
from tools.data_process import DataProcess
from tools.read_file import ReadFile


class Client(Session):
    def __init__(self):
        super(Client, self).__init__()
        self.is_verify = ReadFile.read_config('$.server.is_verify')
        logger.debug(f'平台的SSL请求为：{self.is_verify}')

    def send_request(self, case) -> Any:
        """处理case数据，转换成可用数据发送请求
        :param case: 读取出来的每一行用例内容，可进行解包
        return: 响应结果， 预期结果
        """
        path = case.get('path')
        method = case.get('method')
        parametric_key = case.get('parametric_key')
        header = case.get('header')
        case_id = case.get('case_id')
        case_title = case.get('case_title')
        file_obj = case.get('files')
        data = case.get('data')
        extra = case.get('extra')
        before = case.get('before')
        after = case.get('after')
        expect = case.get('except')

        logger.info(f'执行用例{"*" * 10}{case_title}{"*" * 10}')
        logger.info(
            f"""
        用例进行处理前数据: 
            用例编号({type(case_id)}): {case_id}
            用例标题({type(case_title)}): {case_title}
            接口路径({type(path)}): {path}
            请求头({type(header)}): {header}
            请求方法({type(method)}): {method}
            参数类型({type(parametric_key)}): {parametric_key}
            请求参数({type(data)}): {data}
            文件对象({type(file_obj)}): {file_obj}
            提取参数({type(extra)}): {extra}
            前置操作({type(before)}):{before} 
            后置操作({type(after)}): {after}
            预期结果({type(expect)}): {expect}
            """
        )
        # allure报告 用例标题
        allure_title(case_title)
        # 前置操作
        DataProcess.handle_before(before_dict=before)
        # 处理url、header、data、media、的前置方法
        url = DataProcess.handle_path(path)
        header = DataProcess.handle_header(header)
        data = DataProcess.handle_request_data(data)
        file = DataProcess.handler_files(file_obj)

        logger.info(
            f"""
        用例最终请求数据: 
            用例编号({type(case_id)}): {case_id}
            用例标题({type(case_title)}): {case_title}
            接口路径({type(url)}): {url}
            请求头({type(header)}): {header}
            请求方法({type(method)}): {method}
            参数类型({type(parametric_key)}): {parametric_key}
            请求参数({type(data)}): {data}
            文件对象({type(file_obj)}): {file_obj}
            提取参数({type(extra)}): {extra} 
            后置操作({type(after)}): {after}
            预期结果({type(expect)}): {expect}
        """
        )
        # 发送请求
        response_code, response = self._request(url, method, parametric_key, header, data, file)
        # 提取响应状态码
        DataProcess.handle_response_code(response_code)
        # 提取参数
        DataProcess.handle_extra(extra, response)
        return response, expect, after

    def _request(
            self, url: str, method: str, parametric_key: str, header=None, data=None, file=None
    ) -> tuple:
        """
        :param method: 请求方法
        :param url: 请求url
        :param parametric_key: 入参关键字， params(查询参数类型，明文传输，一般在url?参数名=参数值), data(一般用于form表单类型参数)
        json(一般用于json类型请求参数)
        :param data: 参数数据，默认等于None
        :param file: 文件对象
        :param header: 请求头
        :return: 返回res对象
        """
        parametric_key = parametric_key.lower()
        if parametric_key == 'params':
            extra_args = {'params': data}
        elif parametric_key == 'data':
            extra_args = {'data': data}
        elif parametric_key == 'json':
            extra_args = {'json': data}
        else:
            raise ValueError("可选关键字为params, json, data")

        res = self.request(
            method=method, url=url, files=file, headers=header, verify=self.is_verify, **extra_args
        )
        response_code = res.status_code
        response = res.json()
        logger.info(f'接口请求成功：{response_code}')
        logger.info(
            f"""
                用例响应数据({type(response)}): {response}
            """
        )
        allure_step_no(f"响应耗时(s): {res.elapsed.total_seconds()}")
        allure_step_no(f"响应状态==>{response_code}")
        allure_step("响应结果", response)
        return response_code, response


client = Client()

if __name__ == '__main__':
    data_dict = {'编号': 'test001',
                 '用例标题': '测试新闻头条',
                 '请求头': '',
                 '接口地址': '/toutiao/index',
                 '请求方式': 'get',
                 '入参关键字': 'params',
                 '上传文件': '',
                 '请求数据': '{"key":"774e899ced5927de2cb93fa2a5e12b73","type":"top"}',
                 '提取参数': '{"title":"$.result.data.0.title"}',
                 '后置sql': 'select * from role',
                 '预期结果': '{"$.meta.status":200}'
                 }
    t_response, t_expect, t_sql = client.send_request(data_dict, env='test')
    print(t_response)
    print(t_expect)
    print(t_sql)
